package com.zshy.base.protocol.utils;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Map;
import java.util.Objects;
import java.util.SortedMap;

/**
 * 签名工具类
 *
 * @author :xtp
 * @since :
 **/
@Slf4j
public class SignKit {

    public static String getSign(Map<String, String> data, String secret, String type) {
        if (type.equals("rsa") && type.equals("md5")) {
            return null;
        }
        if (type.equals("rsa")) {
            return sign(data, secret);
        }
        if (type.equals("md5")) {
            return null;
        }
        return null;
    }

    /**
     * 生成对应的 与我通信的公钥和私钥
     *
     * @return
     */
    public static void createRSAKey() {
        try {
            // 创建KeyPairGenerator 指定算法为RSA，用于生成对应的公钥和私钥
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            // 指定字节长度
            keyPairGenerator.initialize(1024);

            // 秘钥生成器
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            // 公钥
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            // 进行Base64编码存入
            String clientPublicKey = Base64.encodeBase64String(publicKey.getEncoded());
            log.info("生成的clientPublicKey是: {}", clientPublicKey);

            // 私钥
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            // 进行Base64编码存入
            String clientPrivateKey = Base64.encodeBase64String(privateKey.getEncoded());
            log.info("生成的clientPrivateKey是: {}", clientPrivateKey);

        } catch (Exception e) {
            log.error("生成秘钥失败");
            e.printStackTrace();
        }
    }


    /**
     * 利用私钥信息生成数字签名
     *
     * @param data       入参数据
     * @param privateKey 私钥
     * @return
     */
    public static String sign(Map<String, String> data, String privateKey) {
        try {
            if (data == null) {
                return null;
            }
            String dataStr = JSON.toJSONString(data);
            // 入参数据字节数组
            byte[] dataBytes = dataStr.getBytes();
            // 获取私钥秘钥字节数组
            byte[] keyBytes = Base64.decodeBase64(privateKey);
            // 使用给定的编码密钥创建一个新的PKCS8EncodedKeySpec。
            // PKCS8EncodedKeySpec 是 PKCS#8标准作为密钥规范管理的编码格式
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            // 实例化KeyFactory,指定为加密算法 为 RSA
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            // 获得PrivateKey对象
            PrivateKey privateKey1 = keyFactory.generatePrivate(keySpec);
            // 用私钥对信息生成数字签名，指定签名算法为 MD5withRSA
            Signature signature = Signature.getInstance("MD5withRSA");
            // 初始化签名
            signature.initSign(privateKey1);
            // 数据带入
            signature.update(dataBytes);
            // 对签名进行Base64编码
            return Base64.encodeBase64String(signature.sign());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 利用公钥校验数字签名
     *
     * @param sortedMap 入参数据
     * @param publicKey 公钥
     * @param sign      签名
     * @return
     */
    public static boolean verify(SortedMap<String, Object> sortedMap, String privateKey, String sign) {
        try {
            if (Objects.isNull(sortedMap) || Objects.isNull(privateKey) || Objects.isNull(sign)) {
                return false;
            }
            //获取当前参数签名
            String thenSign = DigestUtils.md5Hex(JSON.toJSONString(sortedMap));
            thenSign = new BCryptPasswordEncoder().encode(thenSign);
            //使用私钥进行解密
            byte[] buffer = Base64.decodeBase64(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey key = keyFactory.generatePrivate(keySpec);
            Cipher cipher = Cipher.getInstance(key.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, key);
            //获取前端签名
            String clientSign = new String(cipher.doFinal(Base64.decodeBase64(sign)));
            return new BCryptPasswordEncoder().matches(clientSign, thenSign);
        } catch (Exception e) {
            log.warn("验签错误");
            return false;
        }
    }


    public static void main(String[] args) {

        //Map<String, String> map = new HashMap<>();
        ////client_id
        //map.put("appid", "appid");
        //// 请求发起的时间
        //map.put("timestamp", String.valueOf(System.currentTimeMillis()));
        //// 随机数
        //map.put("nonce", String.valueOf(new Random().nextInt()));
        //
        //// 签名算法生成的签名，私钥
        //String sign = SignUtil.sign(map, "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOkdXg8oqKyAVM0GlSoF1LZz6drDfdMqfWCthjAgkrdzL6mxiwywxab+Z1ToMCGL74v8dW3XDltVBZ0dbkOeRB7DpUC4rTL8nwNdGCaCSJeVFZN9/r2+jNPO93d9DN6QwM8p5uMO9IogSZqaO95mk4ePEA+HbTdYuinE0QiAyHrxAgMBAAECgYAa31v1Qw/KrufXqK9vpDNvWEZi2w/5VJfBGiUdYtaMQkGCKNQpgYPkv8VOqDjK19756VTqIBU+Gbt8xKSY3o47MKPIMBNsYDLBP0DMS4hnOElcpXKwm0Kbu/H88zLG7pTkyU+UyTwtDhEtUQKcRWaqU805LKs0xdC0g5TuEXOzXwJBAPvIUS9o5VQiBwqyktnfMycGeaAjIxXJ1QCXTSp/ox4l/3sz2zoKNDCRaZeh3FGub6UjRJhPT/3OiltYFae93hsCQQDtBP/8oGUNUlkeBms0Rf2AbBXbjbMGUAKq0+knds/+39ipK09TQlOlg3PU9Fw0ovU7pN2etdlE8kOw4H93OivjAkAhXcmMe90wShYez81wPAj+WfhSRXXH1Gh63JIoWKPYQfbab+PUjDegXBTfOF8HIBPBkavsd05Fd1KUilbMVPgTAkBZ85PTJGw1ahM4Oedlp0pV+q8w684Njz/z5QiPWaAGcp2fVjh8uKdWIVVMdJCpyU6YnDEfkpQqfmcCMbEuZn1RAkADK4fZHzwe6fo0/zvyQPWhB2dGg/DwBnIOQfvZgZGPvzZn+hA6QoNk8LeWjL9xrX0P/MgobdRvubvNemVgemCc");
        //map.put("sign", sign);
        //
        //System.out.println(sign);
        //公钥
        //boolean verify = SignUtil.verify(map, "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpHV4PKKisgFTNBpUqBdS2c+naw33TKn1grYYwIJK3cy+psYsMsMWm/mdU6DAhi++L/HVt1w5bVQWdHW5DnkQew6VAuK0y/J8DXRgmgkiXlRWTff69vozTzvd3fQzekMDPKebjDvSKIEmamjveZpOHjxAPh203WLopxNEIgMh68QIDAQAB", sign);
        //System.out.println("验签结果：" + verify);
        createRSAKey();
    }
}
